package com.task.utils;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class PageTag extends SimpleTagSupport{
	
	// �?Id;
	private String formId;
	
	// ��������ʾ���ٳ�t��
	private int leftPages = 4;
	
	// �ұ������ʾ���ٳ�t��
	private int rightPages = 2;
	
	// ÿҳ������
	private int pageCount = 1;
	
	// ��һҳ���
	private String firstName = "|&lt;";
	
	// ���һҳ���
	private String lastName = "&gt;|";
	
	// ��һҳ���
	private String prevName = "&lt;";
	
	// ��һҳ���
	private String nextName = "&gt;";
	
	// �Ƿ���ʾ��һҳ
	private boolean showFirst = true;
	
	// �Ƿ���ʾ���һҳ
	private boolean showLast = true;
	
	// �Ƿ���ʾ��һҳ(���ѡ��true��û����һҳ�����û�)
	private boolean showPrev = true;
	
	// �Ƿ���ʾ��һҳ(���ѡ��true��û����һҳ�����û�)
	private boolean showNext = true;
	
	// ��װ����ݺ�ҳ����Ϣ
	private PageBean pageBean;
	
	// Ŀ��ҳ��,������jsp,servlet��
	// ��������Щ���������һ��pageBean���õ�������
	private String targetPage;
	
	// ��Ҫ��ʾ���ֶ�,����������Ϊ�ַ�,��','�ָ�
	// ����: name, pass, birthday
	// Ϊ*��ȫ����ʾ
	private String[] fieldNames;
	
	// ��ͷҪ��ʾ�����,����������Ϊ�ַ�,��','�ָ�
	// ���磺����,����,����
	// �������,����fieldNames
	private String[] headerNames;
	
	// ҳ�浼����ʽ�����
	private String paggingClass = "digg";
	
	// �����ʽ�����
	private String tableClass = "c1";

	@Override
	public void doTag() throws JspException, IOException {
		if(pageBean == null) return;
		StringBuffer total = new StringBuffer(1024);
		genScript(total);		
//		total.append("<table class='"+tableClass+"' cellpadding='0'>");
//		genTHeader(total);
//		genTBody(total);
//		total.append("</table>");
		genPagging(total);
		this.getJspContext().getOut().print(total.toString());
		
	}

	private void genPagging(StringBuffer total) {
		total.append("<div class=\""+paggingClass+"\">");
		if(showFirst){
			if(!pageBean.isPrevious()){
				total.append("<span class=\"disabled\">"+firstName+"</span>");
			} else {
				total.append("<a href='#' onclick=\"goto(1);return false;\">"
						+firstName+"</a>");
			}
		}
		if(showPrev){
			if(!pageBean.isPrevious()){
				total.append("<span class=\"disabled\">"+prevName+"</span>");
			} else {
				total.append("<a href='#' onclick=\"goto("+(pageBean.getPageNo() - 1)+");return false;\">"
						+prevName+"</a>");
			}
		}
		/*
		 * ���� leftPages=5 rightPages=2��ʾ����
		 * 1 |2| 3  4  5 ... 9  10
		 * 1  2 |3| 4  5 ... 9  10
		 * 1  2  3 |4| 5 ... 9  10
		 * 2  3  4 |5| 6 ... 9  10
		 * 3  4  5 |6| 7 ... 9  10
		 * 1  2 ... 6 |7| 8  9  10
		 * 1  2 ... 6  7 |8| 9  10
		 * 1  2 ... 6  7  8 |9| 10
		 * ��� leftPages=7 rightPages=2��ʾʱ��û���м��...��
		 */
		if(leftPages + rightPages + 1 >= pageBean.getTotalPage()){
			for(int i = 1; i <= pageBean.getTotalPage(); i++){
				writeHref(total, i);
			}
		} else {
			int begin = 1;
			int end = pageBean.getTotalPage();
			if(pageBean.getPageNo() >= leftPages) {
				begin = pageBean.getPageNo() - leftPages + 2;
			}
			if(pageBean.getPageNo() + leftPages - 2 <  pageBean.getTotalPage()){
				end = pageBean.getPageNo() + leftPages - 2;
			}
			int middle = pageBean.getTotalPage() / 2;
			
			if(pageBean.getPageNo() < middle + 2){
				for(int i = begin; i < leftPages + begin; i++){
					writeHref(total, i);
				}
				total.append("...");
				for(int i = pageBean.getTotalPage() - rightPages + 1; i <= pageBean.getTotalPage(); i++){
					writeHref(total, i);
				}
			} else {
				for(int i = 1; i <= rightPages; i++){
					writeHref(total, i);
				}
				total.append("...");
				for(int i = end - leftPages + 1; i <= end; i++){
					writeHref(total, i);
				}
			}
			
		}
		if(showNext){
			if(!pageBean.isNext()){
				total.append("<span class=\"disabled\">"+nextName+"</span>");
			} else {
				total.append("<a href='#' onclick=\"goto("+(pageBean.getPageNo() + 1)+");return false;\">"
						+nextName+"</a>");
			}
		}
		if(showLast){
			if(!pageBean.isNext()){
				total.append("<span class=\"disabled\">"+lastName+"</span>");
			} else {
				total.append("<a href='#' onclick=\"goto("+pageBean.getTotalPage()+");return false;\">"
						+lastName+"</a>");
			}
		}
		total.append("</div>");
	}

	private void writeHref(StringBuffer total, int i) {
		if(i == pageBean.getPageNo()){ // ��ǰҳ
			total.append("<span class=\"current\">"+i+"</span>");
		} else {
			total.append("<a href='#' onclick=\"goto("+i+");return false;\">"+i+"</a>");
		}
	}

	private void genTBody(StringBuffer body) {
		body.append("<tbody>");
		for (Iterator iter = pageBean.getObjs().iterator(); iter.hasNext();) {
			body.append("<tr>");
			Object o = (Object) iter.next();
			for (int i = 0; i < fieldNames.length; i++) {
				String field = fieldNames[i].trim();
				Object value = null;
				try {
					Method m = o.getClass().getMethod(field2Method(field,"get"), new Class[]{});
					if(m == null){
						m = o.getClass().getMethod(field2Method(field,"is"), new Class[]{});
					}
					if(m == null) {
						throw new RuntimeException("û�ж�Ӧ�ķ���");
					}
					value = m.invoke(o, null);
				} catch (Exception e) {
				}
				body.append("<td>");
				body.append((value==null)?"":value.toString());
				body.append("</td>");			
			}
			body.append("</tr>");
		}
		body.append("</tbody>");
	}

	private void genTHeader(StringBuffer header) {
		header.append("<thead>");
		if(headerNames == null) {
			headerNames = fieldNames;
		}
		for (int i = 0; i < headerNames.length; i++) {
			String field = headerNames[i];
			header.append("<th>");
			header.append(field);
			header.append("</th>");			
		}
		header.append("</thead>");
	}

	private void genScript(StringBuffer script) {
		script.append("<script type=\"text/javascript\">\n");
		script.append("$(document).ready(function(){\n"+
						// ��ӱ���ż���б���������ƶ�Ч��
						"$('."+tableClass+" tr')\n" +
							".mouseover(function(){$(this).addClass('over');})\n"+
							".mouseout(function(){$(this).removeClass('over');});\n"+
						"$('."+tableClass+" tr:even').addClass('alt');\n" +
						// ���?���Ƿ���pageNo��pageCount�?��û�������
						"var input1 = \"<input id='pageNo' type='hidden' name='pageBean.pageNo' value='1'/>\";\n" + 
						"var input2 = \"<input id='pageCount' type='hidden' name='pageCount' value='"+pageCount+"'/>\";\n" + 
						"if($('#"+formId+" > input[id=\"pageNo\"]').length == 0) {\n" +
							"$('#"+formId+"').append($(input1));\n" + 
						"}\n" + 
						"if($('#"+formId+" > input[id=\"pageCount\"]').length == 0) {\n" +
							"$('#"+formId+"').append($(input2));\n" + 
						"}\n" + 
						"});\n");
		
		
		script.append("function goto(pageNo) {\n" +
						"var form = $('#"+formId+"');\n" +
						"$('#pageNo').attr('value',pageNo);\n" + 
						"form.attr('action','"+targetPage+"');\n" +
						"form.attr('method','POST');\n" +
						"form.submit();\n" +
					  "}\n");
		script.append("</script>");
	}
	
	public String field2Method(String fieldName, String prefix) {
		StringBuffer buffer = new StringBuffer();
        char upperCaseChar = Character.toUpperCase(fieldName.charAt(0));
        buffer.append(prefix).append(upperCaseChar).append(fieldName.substring(1));
        return buffer.toString();        
    }

	public int getLeftPages() {
		return leftPages;
	}


	public void setLeftPages(int leftPages) {
		this.leftPages = leftPages;
	}


	public PageBean getPageBean() {
		return pageBean;
	}


	public void setPageBean(PageBean pageBean) {
		this.pageBean = pageBean;
	}


	public int getRightPages() {
		return rightPages;
	}


	public void setRightPages(int rightPages) {
		this.rightPages = rightPages;
	}

	public void setFieldNames(String fieldNames) {
		if(! "*".equals(fieldNames)) {
			this.fieldNames = fieldNames.split(",");
		} else {
			ArrayList fields = new ArrayList();
			if(pageBean == null || pageBean.getObjs().size() == 0) {
				this.fieldNames = new String[0];
				return;
			}
			Class clazz = pageBean.getObjs().iterator().next().getClass();
			Method[] methods = clazz.getMethods();
			for (int i = 0; i < methods.length; i++) {
				String methodName = methods[i].getName();
				if(methodName.startsWith("get")){
					methodName = methodName.substring(3);
					methodName = Character.toLowerCase(methodName.charAt(0)) + methodName.substring(1);
				} else if(methodName.startsWith("is")){
					methodName = methodName.substring(2);
					methodName = Character.toLowerCase(methodName.charAt(0)) + methodName.substring(1);
				} else {
					continue;
				}
				fields.add(methodName);
			}
			this.fieldNames = (String[])fields.toArray(new String[]{});
		}
	}
	
	public void setHeaderNames(String headerNames) {
		this.headerNames = headerNames.split(",");
	}

	public String getNextName() {
		return nextName;
	}

	public void setNextName(String nextName) {
		this.nextName = nextName;
	}

	public String getPrevName() {
		return prevName;
	}

	public void setPrevName(String prevName) {
		this.prevName = prevName;
	}

	public boolean isShowNext() {
		return showNext;
	}

	public void setShowNext(boolean showNext) {
		this.showNext = showNext;
	}

	public boolean isShowPrev() {
		return showPrev;
	}

	public void setShowPrev(boolean showPrev) {
		this.showPrev = showPrev;
	}

	public String getTargetPage() {
		return targetPage;
	}

	public void setTargetPage(String targetPage) {
		this.targetPage = targetPage;
	}

	public String getFormId() {
		return formId;
	}

	public void setFormId(String formId) {
		this.formId = formId;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public boolean isShowFirst() {
		return showFirst;
	}

	public void setShowFirst(boolean showFirst) {
		this.showFirst = showFirst;
	}

	public boolean isShowLast() {
		return showLast;
	}

	public void setShowLast(boolean showLast) {
		this.showLast = showLast;
	}
	
	public String getPaggingClass() {
		return paggingClass;
	}

	public void setPaggingClass(String paggingClass) {
		this.paggingClass = paggingClass;
	}

	public String getTableClass() {
		return tableClass;
	}

	public void setTableClass(String tableClass) {
		this.tableClass = tableClass;
	}

	public int getPageCount() {
		return pageCount;
	}

	public void setPageCount(int pageCount) {
		this.pageCount = pageCount;
	}

}
